package com.lwq.service.system;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lwq.dao.system.MenuMapper;
import com.lwq.dao.system.RoleMapper;
import com.lwq.exception.ApiException;
import com.lwq.exception.FieldException;
import com.lwq.model.Dto;
import com.lwq.model.system.SysDict;
import com.lwq.model.system.SysMenu;
import com.lwq.model.system.SysRole;
import com.lwq.util.BeanAssistant;
import com.lwq.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2021/6/11
 */
@Service
public class MenuService {

    @Autowired
    private MenuMapper mapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RedisUtil redis;

    /**
     * 接口两用,如已经查过roleId集合 则直接使用
     *
     * @param userId
     * @param ids
     * @return
     */
    public List<SysMenu> getMenuByUser(Long userId, List<Long> ids) {
        List<Long> roleList;
        if (ids == null || ids.isEmpty()) {
            roleList = roleMapper.getRoleIdByUserId(userId, SysRole.ENABLE);
        } else {
            roleList = ids;
        }
        if (!roleList.isEmpty()) {
            return mapper.getMenuByRoleIds(roleList.stream().map(x -> x + "").collect(Collectors.joining(", ")), SysMenu.ENABLE);
        } else {
            return new ArrayList<>();
        }
    }

    public List<SysMenu> queryListNoRecursion() {
        return recursion(mapper.selectList(new QueryWrapper<SysMenu>().eq("status", SysMenu.ENABLE)));
    }

    public List<SysMenu> queryList(Dto dto) {
        return dto == null ? recursion(mapper.selectList(null)) :
                recursion(mapper.selectByMap(dto));
    }

    public void add(SysMenu sysMenu) {
        if (mapper.selectOne(new QueryWrapper<SysMenu>()
                .eq(SysMenu.CODE, sysMenu.getCode())) != null) {
            throw new ApiException("菜单编号重复");
        }
        mapper.insert(sysMenu);
    }

    public void update(SysMenu sysMenu) {
        if (sysMenu.getId() == null) {
            throw new FieldException("id不可为空");
        }
        SysMenu model = mapper.selectById(sysMenu.getId());
        if (!sysMenu.getCode().equals(model.getCode()) &&
                mapper.selectOne(new QueryWrapper<SysMenu>().eq(SysDict.CODE, sysMenu.getCode())) != null) {
            throw new ApiException("菜单编号重复");
        }
        BeanUtils.copyProperties(sysMenu, model, BeanAssistant.getNullPropertyNames(sysMenu));
        mapper.updateById(sysMenu);
    }

    @Transactional(rollbackFor = Exception.class)
    public void del(Long id) {
        List<SysMenu> menus = getChild(mapper.selectById(id), mapper.selectList(null), true);
        if (menus != null && !menus.isEmpty()) {
            mapper.deleteById(id);
            mapper.deleteBatchIds(menus.stream().map(e -> e.getId()).collect(Collectors.toList()));
        } else {
            mapper.deleteById(id);
        }
    }

    /**
     * 把列表递归成层级关系
     *
     * @param list
     * @return
     */
    public static List<SysMenu> recursion(List<SysMenu> list) {
        List<SysMenu> reList = new ArrayList<>();
        reList.addAll(list.stream().filter(e -> e.getParentId() == null || e.getParentId() == 0).collect(Collectors.toList()));
        reList.sort((x, y) -> Integer.compare(x.getSort(), y.getSort()));
        reList.forEach(e -> {
            e.setChildren(getChild(e, list, false));
        });
        return reList;
    }

    /**
     * 递归获取子菜单 或 平行列表
     *
     * @param m
     * @param list
     * @param toList 是否是平行列表
     * @return
     */
    public static List<SysMenu> getChild(SysMenu m, List<SysMenu> list, Boolean toList) {
        List<SysMenu> childList = new ArrayList<>();
        List<SysMenu> toListArray = new ArrayList<>();
        for (SysMenu menu : list) {
            if (menu.getParentId().equals(m.getId())) {
                childList.add(menu);
            }
        }
        if (toList) {
            toListArray.addAll(childList);
        }
        for (SysMenu menu : childList) {
            if (StringUtils.isEmpty(menu.getUrl())) {
                // 递归
                if (!toList) {
                    menu.setChildren(getChild(menu, list, toList));
                } else {
                    toListArray.addAll(getChild(menu, list, toList));
                }
            }
        } // 递归退出条件
        if (childList.size() == 0) {
            return new ArrayList<>();
        }
        childList.sort((x, y) -> Integer.compare(x.getSort(), y.getSort()));
        return toList ? toListArray : childList;
    }

}
